package com.tsk.state.test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.StateContext;
import org.springframework.statemachine.action.Action;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.persist.DefaultStateMachinePersister;
import org.springframework.statemachine.state.State;

import javax.annotation.Resource;
import java.util.EnumSet;

/**
 * @author: 黄嘉振
 * @create: 2023/5/24 17:48
 * @description:
 **/
@Configuration
//@EnableStateMachine(name = "orderStateMachine")
@EnableStateMachineFactory
public class OrderStateMachineConfig
        extends EnumStateMachineConfigurerAdapter<OrderStatus, OrderStatusChangeEvent> {

    @Autowired
    private MyStateMachinePersist myStateMachinePersist;

    @Resource
    private StateMachineFactory<OrderStatus, OrderStatusChangeEvent> stateMachineFactory;

    // 定义状态机入口bean
    @Bean
    public StatemachineService<OrderStatus, OrderStatusChangeEvent, String> myStatemachineService() {
        return new StatemachineServiceBuilder<OrderStatus, OrderStatusChangeEvent, String>()
                .setStateMachineFactory(stateMachineFactory)
                .setStateMachinePersister(new DefaultStateMachinePersister<>(myStateMachinePersist))
                .builder();
    }

    @Override
    public void configure(StateMachineConfigurationConfigurer<OrderStatus, OrderStatusChangeEvent> config)
            throws Exception {
        config
                .withConfiguration()
                .autoStartup(true);
//                .listener(listener());
    }

    /**
     * 配置状态
     *
     * @param states
     * @throws Exception
     */
    @Override
    public void configure(StateMachineStateConfigurer<OrderStatus, OrderStatusChangeEvent> states) throws Exception {
        EnumSet<OrderStatus> orderStatuses = EnumSet.allOf(OrderStatus.class);
        orderStatuses.remove(OrderStatus.FINISH);
        states
                .withStates()
                .initial(OrderStatus.WAIT_PAYMENT)
                .states(orderStatuses).state(OrderStatus.FINISH, action())
                .state(OrderStatus.WAIT_RECEIVE, context -> {
                    System.out.println("event WAIT_RECEIVE action.....start");
                }, context -> {
                    System.out.println("event WAIT_RECEIVE action.....end");
                });
//                .states(EnumSet.allOf(OrderStatus.class));
    }
    /**
     * 配置状态转换事件关系
     *
     * @param transitions
     * @throws Exception
     */
    @Override
    public void configure(StateMachineTransitionConfigurer<OrderStatus, OrderStatusChangeEvent> transitions) throws Exception {
        transitions
                //支付事件:待支付-》待发货
                .withExternal().source(OrderStatus.WAIT_PAYMENT).target(OrderStatus.WAIT_DELIVER)
                .event(OrderStatusChangeEvent.PAYED)
                // 配置action，可以用于扩展为其他模块调用状态服务时的动作，另行新增配置即可
                .action(action())
                .and()
                //发货事件:待发货-》待收货
                .withExternal().source(OrderStatus.WAIT_DELIVER).target(OrderStatus.WAIT_RECEIVE)
                .event(OrderStatusChangeEvent.DELIVERY)
                .and()
                //收货事件:待收货-》已完成
                .withExternal().source(OrderStatus.WAIT_RECEIVE).target(OrderStatus.FINISH)
                .event(OrderStatusChangeEvent.RECEIVED);
    }

//    @Bean
//    public StateMachineListener<OrderStatus, OrderStatusChangeEvent> listener() {
//        return new StateMachineListenerAdapter<OrderStatus, OrderStatusChangeEvent>() {
//            @Override
//            public void stateChanged(State<OrderStatus, OrderStatusChangeEvent> from, State<OrderStatus, OrderStatusChangeEvent> to) {
//                System.out.println(from.getId() + " State change to " + to.getId());
//            }
//        };
//    }

    @Bean
    public Action<OrderStatus, OrderStatusChangeEvent> action() {
        return new Action<OrderStatus, OrderStatusChangeEvent>() {

            @Override
            public void execute(StateContext<OrderStatus, OrderStatusChangeEvent> context) {
                // do something
                System.out.println("event PAYED action.....");
            }
        };
    }
}
